home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2010 April / PCWorld0410.iso / hity wydania / Ubuntu 9.10 PL / karmelkowy-koliberek-desktop-9.10-i386-PL.iso / casper / filesystem.squashfs / usr / share / pyshared / Alacarte / MainWindow.py < prev    next >
Text File  |  2009-10-05  |  24KB  |  635 lines

  1. # -*- coding: utf-8 -*-
  2. #   Alacarte Menu Editor - Simple fd.o Compliant Menu Editor
  3. #   Copyright (C) 2006  Travis Watkins
  4. #
  5. #   This library is free software; you can redistribute it and/or
  6. #   modify it under the terms of the GNU Library General Public
  7. #   License as published by the Free Software Foundation; either
  8. #   version 2 of the License, or (at your option) any later version.
  9. #
  10. #   This library is distributed in the hope that it will be useful,
  11. #   but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. #   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  13. #   Library General Public License for more details.
  14. #
  15. #   You should have received a copy of the GNU Library General Public
  16. #   License along with this library; if not, write to the Free Software
  17. #   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  18.  
  19. import gtk, gmenu, gobject, gio
  20. import cgi, os
  21. import gettext
  22. import subprocess
  23. import urllib
  24. try:
  25.     from Alacarte import config
  26.     gettext.bindtextdomain(config.GETTEXT_PACKAGE,config.localedir)
  27.     gettext.textdomain(config.GETTEXT_PACKAGE)
  28. except:
  29.     pass
  30. _ = gettext.gettext
  31. from Alacarte.MenuEditor import MenuEditor
  32. from Alacarte import util
  33.  
  34. class MainWindow:
  35.     timer = None
  36.     #hack to make editing menu properties work
  37.     allow_update = True
  38.     #drag-and-drop stuff
  39.     dnd_items = [('ALACARTE_ITEM_ROW', gtk.TARGET_SAME_APP, 0), ('text/plain', 0, 1)]
  40.     dnd_menus = [('ALACARTE_MENU_ROW', gtk.TARGET_SAME_APP, 0)]
  41.     dnd_both = [dnd_items[0],] + dnd_menus
  42.     drag_data = None
  43.     edit_pool = []
  44.  
  45.     def __init__(self, datadir, version, argv):
  46.         self.file_path = datadir
  47.         self.version = version
  48.         self.editor = MenuEditor()
  49.         gtk.window_set_default_icon_name('alacarte')
  50.         self.tree = gtk.Builder()
  51.         self.tree.set_translation_domain(config.GETTEXT_PACKAGE)
  52.         self.tree.add_from_file(os.path.join(self.file_path, 'alacarte.ui'))
  53.         self.tree.connect_signals(self)
  54.         self.setupMenuTree()
  55.         self.setupItemTree()
  56.         self.tree.get_object('edit_delete').set_sensitive(False)
  57.         self.tree.get_object('edit_revert_to_original').set_sensitive(False)
  58.         self.tree.get_object('edit_properties').set_sensitive(False)
  59.         self.tree.get_object('move_up_button').set_sensitive(False)
  60.         self.tree.get_object('move_down_button').set_sensitive(False)
  61.         self.tree.get_object('new_separator_button').set_sensitive(False)
  62.         accelgroup = gtk.AccelGroup()
  63.         keyval, modifier = gtk.accelerator_parse('<Ctrl>Z')
  64.         accelgroup.connect_group(keyval, modifier, gtk.ACCEL_VISIBLE, self.on_mainwindow_undo)
  65.         keyval, modifier = gtk.accelerator_parse('<Ctrl><Shift>Z')
  66.         accelgroup.connect_group(keyval, modifier, gtk.ACCEL_VISIBLE, self.on_mainwindow_redo)
  67.         keyval, modifier = gtk.accelerator_parse('F1')
  68.         accelgroup.connect_group(keyval, modifier, gtk.ACCEL_VISIBLE, self.on_help_button_clicked)
  69.         self.tree.get_object('mainwindow').add_accel_group(accelgroup)
  70.  
  71.     def run(self):
  72.         self.loadMenus()
  73.         self.editor.applications.tree.add_monitor(self.menuChanged, None)
  74.         self.editor.settings.tree.add_monitor(self.menuChanged, None)
  75.         self.tree.get_object('mainwindow').show_all()
  76.         gtk.main()
  77.  
  78.     def menuChanged(self, *a):
  79.         if self.timer:
  80.             gobject.source_remove(self.timer)
  81.             self.timer = None
  82.         self.timer = gobject.timeout_add(3, self.loadUpdates)
  83.  
  84.     def loadUpdates(self):
  85.         if not self.allow_update:
  86.             return False
  87.         menu_tree = self.tree.get_object('menu_tree')
  88.         item_tree = self.tree.get_object('item_tree')
  89.         items, iter = item_tree.get_selection().get_selected()
  90.         update_items = False
  91.         item_id, separator_path = None, None
  92.         if iter:
  93.             update_items = True
  94.             if items[iter][3].get_type() == gmenu.TYPE_DIRECTORY:
  95.                 item_id = os.path.split(items[iter][3].get_desktop_file_path())[1]
  96.                 update_items = True
  97.             elif items[iter][3].get_type() == gmenu.TYPE_ENTRY:
  98.                 item_id = items[iter][3].get_desktop_file_id()
  99.                 update_items = True
  100.             elif items[iter][3].get_type() == gmenu.TYPE_SEPARATOR:
  101.                 item_id = items.get_path(iter)
  102.                 update_items = True
  103.         menus, iter = menu_tree.get_selection().get_selected()
  104.         update_menus = False
  105.         menu_id = None
  106.         if iter:
  107.             if menus[iter][2].get_desktop_file_path():
  108.                 menu_id = os.path.split(menus[iter][2].get_desktop_file_path())[1]
  109.             else:
  110.                 menu_id = menus[iter][2].get_menu_id()
  111.             update_menus = True
  112.         self.loadMenus()
  113.         #find current menu in new tree
  114.         if update_menus:
  115.             menu_tree.get_model().foreach(self.findMenu, menu_id)
  116.             menus, iter = menu_tree.get_selection().get_selected()
  117.             if iter:
  118.                 self.on_menu_tree_cursor_changed(menu_tree)
  119.         #find current item in new list
  120.         if update_items:
  121.             i = 0
  122.             for item in item_tree.get_model():
  123.                 found = False
  124.                 if item[3].get_type() == gmenu.TYPE_ENTRY and item[3].get_desktop_file_id() == item_id:
  125.                     found = True
  126.                 if item[3].get_type() == gmenu.TYPE_DIRECTORY and item[3].get_desktop_file_path():
  127.                     if os.path.split(item[3].get_desktop_file_path())[1] == item_id:
  128.                         found = True
  129.                 if item[3].get_type() == gmenu.TYPE_SEPARATOR:
  130.                     if not isinstance(item_id, tuple):
  131.                         continue
  132.                     #separators have no id, have to find them manually
  133.                     #probably won't work with two separators together
  134.                     if (item_id[0] - 1,) == (i,):
  135.                         found = True
  136.                     elif (item_id[0] + 1,) == (i,):
  137.                         found = True
  138.                     elif (item_id[0],) == (i,):
  139.                         found = True
  140.                 if found:
  141.                     item_tree.get_selection().select_path((i,))
  142.                     self.on_item_tree_cursor_changed(item_tree)
  143.                     break
  144.                 i += 1
  145.         return False
  146.  
  147.     def findMenu(self, menus, path, iter, menu_id):
  148.         if not menus[path][2].get_desktop_file_path():
  149.             if menu_id == menus[path][2].get_menu_id():
  150.                 menu_tree = self.tree.get_object('menu_tree')
  151.                 menu_tree.expand_to_path(path)
  152.                 menu_tree.get_selection().select_path(path)
  153.                 return True
  154.             return False
  155.         if os.path.split(menus[path][2].get_desktop_file_path())[1] == menu_id:
  156.             menu_tree = self.tree.get_object('menu_tree')
  157.             menu_tree.expand_to_path(path)
  158.             menu_tree.get_selection().select_path(path)
  159.             return True
  160.  
  161.     def setupMenuTree(self):
  162.         self.menu_store = gtk.TreeStore(gtk.gdk.Pixbuf, str, object)
  163.         menus = self.tree.get_object('menu_tree')
  164.         column = gtk.TreeViewColumn(_('Name'))
  165.         column.set_spacing(4)
  166.         cell = gtk.CellRendererPixbuf()
  167.         column.pack_start(cell, False)
  168.         column.set_attributes(cell, pixbuf=0)
  169.         cell = gtk.CellRendererText()
  170.         cell.set_fixed_size(-1, 25)
  171.         column.pack_start(cell, True)
  172.         column.set_attributes(cell, markup=1)
  173.         column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
  174.         menus.append_column(column)
  175.         menus.enable_model_drag_source(gtk.gdk.BUTTON1_MASK, self.dnd_menus, gtk.gdk.ACTION_COPY)
  176.         menus.enable_model_drag_dest(self.dnd_both, gtk.gdk.ACTION_PRIVATE)
  177.  
  178.     def setupItemTree(self):
  179.         items = self.tree.get_object('item_tree')
  180.         column = gtk.TreeViewColumn(_('Show'))
  181.         cell = gtk.CellRendererToggle()
  182.         cell.connect('toggled', self.on_item_tree_show_toggled)
  183.         column.pack_start(cell, True)
  184.         column.set_attributes(cell, active=0)
  185.         #hide toggle for separators
  186.         column.set_cell_data_func(cell, self._cell_data_toggle_func)
  187.         items.append_column(column)
  188.         column = gtk.TreeViewColumn(_('Item'))
  189.         column.set_spacing(4)
  190.         cell = gtk.CellRendererPixbuf()
  191.         column.pack_start(cell, False)
  192.         column.set_attributes(cell, pixbuf=1)
  193.         cell = gtk.CellRendererText()
  194.         cell.set_fixed_size(-1, 25)
  195.         column.pack_start(cell, True)
  196.         column.set_attributes(cell, markup=2)
  197.         items.append_column(column)
  198.         self.item_store = gtk.ListStore(bool, gtk.gdk.Pixbuf, str, object)
  199.         items.set_model(self.item_store)
  200.         items.enable_model_drag_source(gtk.gdk.BUTTON1_MASK, self.dnd_items, gtk.gdk.ACTION_COPY)
  201.         items.enable_model_drag_dest(self.dnd_items, gtk.gdk.ACTION_PRIVATE)
  202.  
  203.     def _cell_data_toggle_func(self, tree_column, renderer, model, treeiter):
  204.         if model[treeiter][3].get_type() == gmenu.TYPE_SEPARATOR:
  205.             renderer.set_property('visible', False)
  206.         else:
  207.             renderer.set_property('visible', True)
  208.  
  209.     def loadMenus(self):
  210.         self.menu_store.clear()
  211.         for menu in self.editor.getMenus():
  212.             iters = [None]*20
  213.             self.loadMenu(iters, menu)
  214.         menu_tree = self.tree.get_object('menu_tree')
  215.         menu_tree.set_model(self.menu_store)
  216.         for menu in self.menu_store:
  217.             #this might not work for some reason
  218.             try:
  219.                 menu_tree.expand_to_path(menu.path)
  220.             except:
  221.                 pass
  222.         menu_tree.get_selection().select_path((0,))
  223.         self.on_menu_tree_cursor_changed(menu_tree)
  224.  
  225.     def loadMenu(self, iters, parent, depth=0):
  226.         if depth == 0:
  227.             icon = util.getIcon(parent)
  228.             iters[depth] = self.menu_store.append(None, (icon, cgi.escape(parent.get_name()), parent))
  229.         depth += 1
  230.         for menu, show in self.editor.getMenus(parent):
  231.             if show:
  232.                 name = cgi.escape(menu.get_name())
  233.             else:
  234.                 name = '<small><i>' + cgi.escape(menu.get_name()) + '</i></small>'
  235.             icon = util.getIcon(menu)
  236.             iters[depth] = self.menu_store.append(iters[depth-1], (icon, name, menu))
  237.             self.loadMenu(iters, menu, depth)
  238.         depth -= 1
  239.  
  240.     def loadItems(self, menu, menu_path):
  241.         self.item_store.clear()
  242.         for item, show in self.editor.getItems(menu):
  243.             menu_icon = None
  244.             if item.get_type() == gmenu.TYPE_SEPARATOR:
  245.                 name = '---'
  246.                 icon = None
  247.             elif item.get_type() == gmenu.TYPE_ENTRY:
  248.                 if show:
  249.                     name = cgi.escape(item.get_display_name())
  250.                 else:
  251.                     name = '<small><i>' + cgi.escape(item.get_display_name()) + '</i></small>'
  252.                 icon = util.getIcon(item)
  253.             else:
  254.                 if show:
  255.                     name = cgi.escape(item.get_name())
  256.                 else:
  257.                     name = '<small><i>' + cgi.escape(item.get_name()) + '</i></small>'
  258.                 icon = util.getIcon(item)
  259.             self.item_store.append((show, icon, name, item))
  260.  
  261.     #this is a little timeout callback to insert new items after
  262.     #gnome-desktop-item-edit has finished running
  263.     def waitForNewItemProcess(self, process, parent_id, file_path):
  264.         if process.poll() != None:
  265.             if os.path.isfile(file_path):
  266.                 self.editor.insertExternalItem(os.path.split(file_path)[1], parent_id)
  267.             return False
  268.         return True
  269.  
  270.     def waitForNewMenuProcess(self, process, parent_id, file_path):
  271.         if process.poll() != None:
  272.             #hack for broken gnome-desktop-item-edit
  273.             broken_path = os.path.join(os.path.split(file_path)[0], '.directory')
  274.             if os.path.isfile(broken_path):
  275.                 os.rename(broken_path, file_path)
  276.             if os.path.isfile(file_path):
  277.                 self.editor.insertExternalMenu(os.path.split(file_path)[1], parent_id)
  278.             return False
  279.         return True
  280.  
  281.     #this callback keeps you from editing the same item twice
  282.     def waitForEditProcess(self, process, file_path):
  283.         if process.poll() != None:
  284.             self.edit_pool.remove(file_path)
  285.             return False
  286.         return True
  287.  
  288.     def on_new_menu_button_clicked(self, button):
  289.         menu_tree = self.tree.get_object('menu_tree')
  290.         menus, iter = menu_tree.get_selection().get_selected()
  291.         if not iter:
  292.             parent = menus[(0,)][2]
  293.             menu_tree.expand_to_path((0,))
  294.             menu_tree.get_selection().select_path((0,))
  295.         else:
  296.             parent = menus[iter][2]
  297.         file_path = os.path.join(util.getUserDirectoryPath(), util.getUniqueFileId('alacarte-made', '.directory'))
  298.         process = subprocess.Popen(['gnome-desktop-item-edit', file_path], env=os.environ)
  299.         gobject.timeout_add(100, self.waitForNewMenuProcess, process, parent.menu_id, file_path)
  300.  
  301.     def on_new_item_button_clicked(self, button):
  302.         menu_tree = self.tree.get_object('menu_tree')
  303.         menus, iter = menu_tree.get_selection().get_selected()
  304.         if not iter:
  305.             parent = menus[(0,)][2]
  306.             menu_tree.expand_to_path((0,))
  307.             menu_tree.get_selection().select_path((0,))
  308.         else:
  309.             parent = menus[iter][2]
  310.         file_path = os.path.join(util.getUserItemPath(), util.getUniqueFileId('alacarte-made', '.desktop'))
  311.         process = subprocess.Popen(['gnome-desktop-item-edit', file_path], env=os.environ)
  312.         gobject.timeout_add(100, self.waitForNewItemProcess, process, parent.menu_id, file_path)
  313.  
  314.     def on_new_separator_button_clicked(self, button):
  315.         item_tree = self.tree.get_object('item_tree')
  316.         items, iter = item_tree.get_selection().get_selected()
  317.         if not iter:
  318.             return
  319.         else:
  320.             after = items[iter][3]
  321.             menu_tree = self.tree.get_object('menu_tree')
  322.             menus, iter = menu_tree.get_selection().get_selected()
  323.             parent = menus[iter][2]
  324.             self.editor.createSeparator(parent, after=after)
  325.  
  326.     def on_edit_delete_activate(self, menu):
  327.         item_tree = self.tree.get_object('item_tree')
  328.         items, iter = item_tree.get_selection().get_selected()
  329.         if not iter:
  330.             return
  331.         item = items[iter][3]
  332.         if item.get_type() == gmenu.TYPE_ENTRY:
  333.             self.editor.deleteItem(item)
  334.         elif item.get_type() == gmenu.TYPE_DIRECTORY:
  335.             self.editor.deleteMenu(item)
  336.         elif item.get_type() == gmenu.TYPE_SEPARATOR:
  337.             self.editor.deleteSeparator(item)
  338.  
  339.     def on_edit_revert_to_original_activate(self, menu):
  340.         item_tree = self.tree.get_object('item_tree')
  341.         items, iter = item_tree.get_selection().get_selected()
  342.         if not iter:
  343.             return
  344.         item = items[iter][3]
  345.         if item.get_type() == gmenu.TYPE_ENTRY:
  346.             self.editor.revertItem(item)
  347.         elif item.get_type() == gmenu.TYPE_DIRECTORY:
  348.             self.editor.revertMenu(item)
  349.  
  350.     def on_edit_properties_activate(self, menu):
  351.         item_tree = self.tree.get_object('item_tree')
  352.         items, iter = item_tree.get_selection().get_selected()
  353.         if not iter:
  354.             return
  355.         item = items[iter][3]
  356.         if item.get_type() not in (gmenu.TYPE_ENTRY, gmenu.TYPE_DIRECTORY):
  357.             return
  358.  
  359.         if item.get_type() == gmenu.TYPE_ENTRY:
  360.             file_path = os.path.join(util.getUserItemPath(), item.get_desktop_file_id())
  361.             file_type = 'Item'
  362.         elif item.get_type() == gmenu.TYPE_DIRECTORY:
  363.             if item.get_desktop_file_path() == None:
  364.                 file_path = util.getUniqueFileId('alacarte-made', '.directory')
  365.                 parser = util.DesktopParser(file_path, 'Directory')
  366.                 parser.set('Name', item.get_name())
  367.                 parser.set('Comment', item.get_comment())
  368.                 parser.set('Icon', item.get_icon())
  369.                 parser.write(open(file_path))
  370.             else:
  371.                 file_path = os.path.join(util.getUserDirectoryPath(), os.path.split(item.get_desktop_file_path())[1])
  372.             file_type = 'Menu'
  373.  
  374.         if not os.path.isfile(file_path):
  375.             data = open(item.get_desktop_file_path()).read()
  376.             open(file_path, 'w').write(data)
  377.             self.editor._MenuEditor__addUndo([(file_type, os.path.split(file_path)[1]),])
  378.         else:
  379.             self.editor._MenuEditor__addUndo([item,])
  380.         if file_path not in self.edit_pool:
  381.             self.edit_pool.append(file_path)
  382.             process = subprocess.Popen(['gnome-desktop-item-edit', file_path], env=os.environ)
  383.             gobject.timeout_add(100, self.waitForEditProcess, process, file_path)
  384.  
  385.     def on_menu_tree_cursor_changed(self, treeview):
  386.         menus, iter = treeview.get_selection().get_selected()
  387.         menu_path = menus.get_path(iter)
  388.         item_tree = self.tree.get_object('item_tree')
  389.         item_tree.get_selection().unselect_all()
  390.         self.loadItems(self.menu_store[menu_path][2], menu_path)
  391.         self.tree.get_object('edit_delete').set_sensitive(False)
  392.         self.tree.get_object('edit_revert_to_original').set_sensitive(False)
  393.         self.tree.get_object('edit_properties').set_sensitive(False)
  394.         self.tree.get_object('move_up_button').set_sensitive(False)
  395.         self.tree.get_object('move_down_button').set_sensitive(False)
  396.         self.tree.get_object('new_separator_button').set_sensitive(False)
  397.         self.tree.get_object('properties_button').set_sensitive(False)
  398.         self.tree.get_object('delete_button').set_sensitive(False)
  399.  
  400.     def on_menu_tree_drag_data_get(self, treeview, context, selection, target_id, etime):
  401.         menus, iter = treeview.get_selection().get_selected()
  402.         self.drag_data = menus[iter][2]
  403.  
  404.     def on_menu_tree_drag_data_received(self, treeview, context, x, y, selection, info, etime):
  405.         menus = treeview.get_model()
  406.         drop_info = treeview.get_dest_row_at_pos(x, y)
  407.         if drop_info:
  408.             path, position = drop_info
  409.             types = (gtk.TREE_VIEW_DROP_INTO_OR_BEFORE, gtk.TREE_VIEW_DROP_INTO_OR_AFTER)
  410.             if position not in types:
  411.                 context.finish(False, False, etime)
  412.                 return False
  413.             if selection.target in ('ALACARTE_ITEM_ROW', 'ALACARTE_MENU_ROW'):
  414.                 if self.drag_data == None:
  415.                     return False
  416.                 item = self.drag_data
  417.                 new_parent = menus[path][2]
  418.                 treeview.get_selection().select_path(path)
  419.                 if item.get_type() == gmenu.TYPE_ENTRY:
  420.                     self.editor.copyItem(item, new_parent)
  421.                 elif item.get_type() == gmenu.TYPE_DIRECTORY:
  422.                     if self.editor.moveMenu(item, new_parent) == False:
  423.                         self.loadUpdates()
  424.                 else:
  425.                     context.finish(False, False, etime) 
  426.                 context.finish(True, True, etime)
  427.         self.drag_data = None
  428.  
  429.     def on_item_tree_show_toggled(self, cell, path):
  430.         item = self.item_store[path][3]
  431.         if item.get_type() == gmenu.TYPE_SEPARATOR:
  432.             return
  433.         if self.item_store[path][0]:
  434.             self.editor.setVisible(item, False)
  435.         else:
  436.             self.editor.setVisible(item, True)
  437.         self.item_store[path][0] = not self.item_store[path][0]
  438.  
  439.     def on_item_tree_cursor_changed(self, treeview):
  440.         items, iter = treeview.get_selection().get_selected()
  441.         if iter is None:
  442.             return
  443.         item = items[iter][3]
  444.         self.tree.get_object('edit_delete').set_sensitive(True)
  445.         self.tree.get_object('new_separator_button').set_sensitive(True)
  446.         self.tree.get_object('delete_button').set_sensitive(True)
  447.         if self.editor.canRevert(item):
  448.             self.tree.get_object('edit_revert_to_original').set_sensitive(True)
  449.         else:
  450.             self.tree.get_object('edit_revert_to_original').set_sensitive(False)
  451.         if not item.get_type() == gmenu.TYPE_SEPARATOR:
  452.             self.tree.get_object('edit_properties').set_sensitive(True)
  453.             self.tree.get_object('properties_button').set_sensitive(True)
  454.         else:
  455.             self.tree.get_object('edit_properties').set_sensitive(False)
  456.             self.tree.get_object('properties_button').set_sensitive(False)
  457.  
  458.         # If first item...
  459.         if items.get_path(iter)[0] == 0:
  460.             self.tree.get_object('move_up_button').set_sensitive(False)
  461.         else:
  462.             self.tree.get_object('move_up_button').set_sensitive(True)
  463.  
  464.         # If last item...
  465.         if items.get_path(iter)[0] == (len(items)-1):
  466.             self.tree.get_object('move_down_button').set_sensitive(False)
  467.         else:
  468.             self.tree.get_object('move_down_button').set_sensitive(True)
  469.  
  470.     def on_item_tree_row_activated(self, treeview, path, column):
  471.         self.on_edit_properties_activate(None)
  472.  
  473.     def on_item_tree_popup_menu(self, item_tree, event=None):
  474.         model, iter = item_tree.get_selection().get_selected()
  475.         if event:
  476.             #don't show if it's not the right mouse button
  477.             if event.button != 3:
  478.                 return
  479.             button = event.button
  480.             event_time = event.time
  481.             info = item_tree.get_path_at_pos(int(event.x), int(event.y))
  482.             if info != None:
  483.                 path, col, cellx, celly = info
  484.                 item_tree.grab_focus()
  485.                 item_tree.set_cursor(path, col, 0)
  486.         else:
  487.             path = model.get_path(iter)
  488.             button = 0
  489.             event_time = 0
  490.             item_tree.grab_focus()
  491.             item_tree.set_cursor(path, item_tree.get_columns()[0], 0)
  492.         popup = self.tree.get_object('edit_menu')
  493.         popup.popup(None, None, None, button, event_time)
  494.         #without this shift-f10 won't work
  495.         return True
  496.  
  497.     def on_item_tree_drag_data_get(self, treeview, context, selection, target_id, etime):
  498.         items, iter = treeview.get_selection().get_selected()
  499.         self.drag_data = items[iter][3]
  500.  
  501.     def on_item_tree_drag_data_received(self, treeview, context, x, y, selection, info, etime):
  502.         items = treeview.get_model()
  503.         types = (gtk.TREE_VIEW_DROP_BEFORE,    gtk.TREE_VIEW_DROP_INTO_OR_BEFORE)
  504.         if selection.target == 'ALACARTE_ITEM_ROW':
  505.             drop_info = treeview.get_dest_row_at_pos(x, y)
  506.             before = None
  507.             after = None
  508.             if self.drag_data == None:
  509.                 return False
  510.             item = self.drag_data
  511.             if drop_info:
  512.                 path, position = drop_info
  513.                 if position in types:
  514.                     before = items[path][3]
  515.                 else:
  516.                     after = items[path][3]
  517.             else:
  518.                 path = (len(items) - 1,)
  519.                 after = items[path][3]
  520.             if item.get_type() == gmenu.TYPE_ENTRY:
  521.                 self.editor.moveItem(item, item.get_parent(), before, after)
  522.             elif item.get_type() == gmenu.TYPE_DIRECTORY:
  523.                 if self.editor.moveMenu(item, item.get_parent(), before, after) == False:
  524.                     self.loadUpdates()
  525.             elif item.get_type() == gmenu.TYPE_SEPARATOR:
  526.                 self.editor.moveSeparator(item, item.get_parent(), before, after)
  527.             context.finish(True, True, etime)
  528.         elif selection.target == 'text/plain':
  529.             if selection.data == None:
  530.                 return False
  531.             menus, iter = self.tree.get_object('menu_tree').get_selection().get_selected()
  532.             parent = menus[iter][2]
  533.             drop_info = treeview.get_dest_row_at_pos(x, y)
  534.             before = None
  535.             after = None
  536.             if drop_info:
  537.                 path, position = drop_info
  538.                 if position in types:
  539.                     before = items[path][3]
  540.                 else:
  541.                     after = items[path][3]
  542.             else:
  543.                 path = (len(items) - 1,)
  544.                 after = items[path][3]
  545.             file_path = urllib.unquote(selection.data).strip()
  546.             if not file_path.startswith('file:'):
  547.                 return
  548.             myfile = gio.File(uri=file_path)
  549.             file_info = myfile.query_info(gio.FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE)
  550.             content_type = file_info.get_content_type()
  551.             if content_type == 'application/x-desktop':
  552.                 input_stream = myfile.read()
  553.                 open('/tmp/alacarte-dnd.desktop', 'w').write(input_stream.read())
  554.                 parser = util.DesktopParser('/tmp/alacarte-dnd.desktop')
  555.                 self.editor.createItem(parent, parser.get('Icon'), parser.get('Name', self.editor.locale), parser.get('Comment', self.editor.locale), parser.get('Exec'), parser.get('Terminal'), before, after)
  556.             elif content_type in ('application/x-shellscript', 'application/x-executable'):
  557.                 self.editor.createItem(parent, None, os.path.split(file_path)[1].strip(), None, file_path.replace('file://', '').strip(), False, before, after)
  558.         self.drag_data = None
  559.  
  560.     def on_item_tree_key_press_event(self, item_tree, event):
  561.         if event.keyval == gtk.keysyms.Delete:
  562.             self.on_edit_delete_activate(item_tree)
  563.  
  564.     def on_move_up_button_clicked(self, button):
  565.         item_tree = self.tree.get_object('item_tree')
  566.         items, iter = item_tree.get_selection().get_selected()
  567.         if not iter:
  568.             return
  569.         path = items.get_path(iter)
  570.         #at top, can't move up
  571.         if path[0] == 0:
  572.             return
  573.         item = items[path][3]
  574.         before = items[(path[0] - 1,)][3]
  575.         if item.get_type() == gmenu.TYPE_ENTRY:
  576.             self.editor.moveItem(item, item.get_parent(), before=before)
  577.         elif item.get_type() == gmenu.TYPE_DIRECTORY:
  578.             self.editor.moveMenu(item, item.get_parent(), before=before)
  579.         elif item.get_type() == gmenu.TYPE_SEPARATOR:
  580.             self.editor.moveSeparator(item, item.get_parent(), before=before)
  581.  
  582.     def on_move_down_button_clicked(self, button):
  583.         item_tree = self.tree.get_object('item_tree')
  584.         items, iter = item_tree.get_selection().get_selected()
  585.         if not iter:
  586.             return
  587.         path = items.get_path(iter)
  588.         #at bottom, can't move down
  589.         if path[0] == (len(items) - 1):
  590.             return
  591.         item = items[path][3]
  592.         after = items[path][3]
  593.         if item.get_type() == gmenu.TYPE_ENTRY:
  594.             self.editor.moveItem(item, item.get_parent(), after=after)
  595.         elif item.get_type() == gmenu.TYPE_DIRECTORY:
  596.             self.editor.moveMenu(item, item.get_parent(), after=after)
  597.         elif item.get_type() == gmenu.TYPE_SEPARATOR:
  598.             self.editor.moveSeparator(item, item.get_parent(), after=after)
  599.  
  600.     def on_mainwindow_undo(self, accelgroup, window, keyval, modifier):
  601.         self.editor.undo()
  602.  
  603.     def on_mainwindow_redo(self, accelgroup, window, keyval, modifier):
  604.         self.editor.redo()
  605.  
  606.     def on_help_button_clicked(self, *args):
  607.         gtk.show_uri(gtk.gdk.screen_get_default(), "ghelp:user-guide#menu-editor", gtk.get_current_event_time())
  608.  
  609.     def on_revert_button_clicked(self, button):
  610.         dialog = self.tree.get_object('revertdialog')
  611.         dialog.set_transient_for(self.tree.get_object('mainwindow'))
  612.         dialog.show_all()
  613.         if dialog.run() == gtk.RESPONSE_YES:
  614.             self.editor.revert()
  615.         dialog.hide()
  616.  
  617.     def on_close_button_clicked(self, button):
  618.         try:
  619.             self.tree.get_object('mainwindow').hide()
  620.         except:
  621.             pass
  622.         gobject.timeout_add(10, self.quit)
  623.  
  624.     def on_properties_button_clicked(self, button):
  625.         self.on_edit_properties_activate(None)
  626.     def on_delete_button_clicked(self, button):
  627.         self.on_edit_delete_activate(None)
  628.  
  629.     def on_style_set(self, *args):
  630.         self.loadUpdates()
  631.  
  632.     def quit(self):
  633.         self.editor.quit()
  634.         gtk.main_quit()        
  635.